/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package Control;

import Control.exceptions.NonexistentEntityException;
import Control.exceptions.PreexistingEntityException;
import Entidades.Firma;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import Entidades.TipoTarjeta;
import java.util.ArrayList;
import java.util.List;
import Entidades.Tarjeta;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author USUARIO
 */
public class FirmaJpaController implements Serializable {

    public FirmaJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Firma firma) throws PreexistingEntityException, Exception {
        if (firma.getTipoTarjetaList() == null) {
            firma.setTipoTarjetaList(new ArrayList<TipoTarjeta>());
        }
        if (firma.getTarjetaList() == null) {
            firma.setTarjetaList(new ArrayList<Tarjeta>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            List<TipoTarjeta> attachedTipoTarjetaList = new ArrayList<TipoTarjeta>();
            for (TipoTarjeta tipoTarjetaListTipoTarjetaToAttach : firma.getTipoTarjetaList()) {
                tipoTarjetaListTipoTarjetaToAttach = em.getReference(tipoTarjetaListTipoTarjetaToAttach.getClass(), tipoTarjetaListTipoTarjetaToAttach.getIdTipo());
                attachedTipoTarjetaList.add(tipoTarjetaListTipoTarjetaToAttach);
            }
            firma.setTipoTarjetaList(attachedTipoTarjetaList);
            List<Tarjeta> attachedTarjetaList = new ArrayList<Tarjeta>();
            for (Tarjeta tarjetaListTarjetaToAttach : firma.getTarjetaList()) {
                tarjetaListTarjetaToAttach = em.getReference(tarjetaListTarjetaToAttach.getClass(), tarjetaListTarjetaToAttach.getNroTransaccion());
                attachedTarjetaList.add(tarjetaListTarjetaToAttach);
            }
            firma.setTarjetaList(attachedTarjetaList);
            em.persist(firma);
            for (TipoTarjeta tipoTarjetaListTipoTarjeta : firma.getTipoTarjetaList()) {
                tipoTarjetaListTipoTarjeta.getFirmaList().add(firma);
                tipoTarjetaListTipoTarjeta = em.merge(tipoTarjetaListTipoTarjeta);
            }
            for (Tarjeta tarjetaListTarjeta : firma.getTarjetaList()) {
                Firma oldFirmaOfTarjetaListTarjeta = tarjetaListTarjeta.getFirma();
                tarjetaListTarjeta.setFirma(firma);
                tarjetaListTarjeta = em.merge(tarjetaListTarjeta);
                if (oldFirmaOfTarjetaListTarjeta != null) {
                    oldFirmaOfTarjetaListTarjeta.getTarjetaList().remove(tarjetaListTarjeta);
                    oldFirmaOfTarjetaListTarjeta = em.merge(oldFirmaOfTarjetaListTarjeta);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findFirma(firma.getIdFirma()) != null) {
                throw new PreexistingEntityException("Firma " + firma + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Firma firma) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Firma persistentFirma = em.find(Firma.class, firma.getIdFirma());
            List<TipoTarjeta> tipoTarjetaListOld = persistentFirma.getTipoTarjetaList();
            List<TipoTarjeta> tipoTarjetaListNew = firma.getTipoTarjetaList();
            List<Tarjeta> tarjetaListOld = persistentFirma.getTarjetaList();
            List<Tarjeta> tarjetaListNew = firma.getTarjetaList();
            List<TipoTarjeta> attachedTipoTarjetaListNew = new ArrayList<TipoTarjeta>();
            for (TipoTarjeta tipoTarjetaListNewTipoTarjetaToAttach : tipoTarjetaListNew) {
                tipoTarjetaListNewTipoTarjetaToAttach = em.getReference(tipoTarjetaListNewTipoTarjetaToAttach.getClass(), tipoTarjetaListNewTipoTarjetaToAttach.getIdTipo());
                attachedTipoTarjetaListNew.add(tipoTarjetaListNewTipoTarjetaToAttach);
            }
            tipoTarjetaListNew = attachedTipoTarjetaListNew;
            firma.setTipoTarjetaList(tipoTarjetaListNew);
            List<Tarjeta> attachedTarjetaListNew = new ArrayList<Tarjeta>();
            for (Tarjeta tarjetaListNewTarjetaToAttach : tarjetaListNew) {
                tarjetaListNewTarjetaToAttach = em.getReference(tarjetaListNewTarjetaToAttach.getClass(), tarjetaListNewTarjetaToAttach.getNroTransaccion());
                attachedTarjetaListNew.add(tarjetaListNewTarjetaToAttach);
            }
            tarjetaListNew = attachedTarjetaListNew;
            firma.setTarjetaList(tarjetaListNew);
            firma = em.merge(firma);
            for (TipoTarjeta tipoTarjetaListOldTipoTarjeta : tipoTarjetaListOld) {
                if (!tipoTarjetaListNew.contains(tipoTarjetaListOldTipoTarjeta)) {
                    tipoTarjetaListOldTipoTarjeta.getFirmaList().remove(firma);
                    tipoTarjetaListOldTipoTarjeta = em.merge(tipoTarjetaListOldTipoTarjeta);
                }
            }
            for (TipoTarjeta tipoTarjetaListNewTipoTarjeta : tipoTarjetaListNew) {
                if (!tipoTarjetaListOld.contains(tipoTarjetaListNewTipoTarjeta)) {
                    tipoTarjetaListNewTipoTarjeta.getFirmaList().add(firma);
                    tipoTarjetaListNewTipoTarjeta = em.merge(tipoTarjetaListNewTipoTarjeta);
                }
            }
            for (Tarjeta tarjetaListOldTarjeta : tarjetaListOld) {
                if (!tarjetaListNew.contains(tarjetaListOldTarjeta)) {
                    tarjetaListOldTarjeta.setFirma(null);
                    tarjetaListOldTarjeta = em.merge(tarjetaListOldTarjeta);
                }
            }
            for (Tarjeta tarjetaListNewTarjeta : tarjetaListNew) {
                if (!tarjetaListOld.contains(tarjetaListNewTarjeta)) {
                    Firma oldFirmaOfTarjetaListNewTarjeta = tarjetaListNewTarjeta.getFirma();
                    tarjetaListNewTarjeta.setFirma(firma);
                    tarjetaListNewTarjeta = em.merge(tarjetaListNewTarjeta);
                    if (oldFirmaOfTarjetaListNewTarjeta != null && !oldFirmaOfTarjetaListNewTarjeta.equals(firma)) {
                        oldFirmaOfTarjetaListNewTarjeta.getTarjetaList().remove(tarjetaListNewTarjeta);
                        oldFirmaOfTarjetaListNewTarjeta = em.merge(oldFirmaOfTarjetaListNewTarjeta);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = firma.getIdFirma();
                if (findFirma(id) == null) {
                    throw new NonexistentEntityException("The firma with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Firma firma;
            try {
                firma = em.getReference(Firma.class, id);
                firma.getIdFirma();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The firma with id " + id + " no longer exists.", enfe);
            }
            List<TipoTarjeta> tipoTarjetaList = firma.getTipoTarjetaList();
            for (TipoTarjeta tipoTarjetaListTipoTarjeta : tipoTarjetaList) {
                tipoTarjetaListTipoTarjeta.getFirmaList().remove(firma);
                tipoTarjetaListTipoTarjeta = em.merge(tipoTarjetaListTipoTarjeta);
            }
            List<Tarjeta> tarjetaList = firma.getTarjetaList();
            for (Tarjeta tarjetaListTarjeta : tarjetaList) {
                tarjetaListTarjeta.setFirma(null);
                tarjetaListTarjeta = em.merge(tarjetaListTarjeta);
            }
            em.remove(firma);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Firma> findFirmaEntities() {
        return findFirmaEntities(true, -1, -1);
    }

    public List<Firma> findFirmaEntities(int maxResults, int firstResult) {
        return findFirmaEntities(false, maxResults, firstResult);
    }

    private List<Firma> findFirmaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Firma.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Firma findFirma(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Firma.class, id);
        } finally {
            em.close();
        }
    }

    public int getFirmaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Firma> rt = cq.from(Firma.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
